home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Util / Misc / AssignWedge.lha / Source / AssignWedge.c < prev    next >
C/C++ Source or Header  |  1995-01-18  |  24KB  |  1,067 lines

  1. /*
  2. **    AssignWedge - AmigaDOS 2.04 utility
  3. **
  4. **    Copyright © 1992-1994 by Olaf `Olsen' Barthel
  5. **        All Rights Reserved
  6. **
  7. ** :ts=4
  8. */
  9.  
  10. #include <intuition/intuitionbase.h>
  11.  
  12. #include <workbench/startup.h>
  13.  
  14. #include <dos/dosextens.h>
  15. #include <dos/dostags.h>
  16.  
  17. #include <exec/execbase.h>
  18. #include <exec/memory.h>
  19.  
  20. #include <libraries/locale.h>
  21. #include <libraries/asl.h>
  22.  
  23. #include <clib/intuition_protos.h>
  24. #include <clib/utility_protos.h>
  25. #include <clib/locale_protos.h>
  26. #include <clib/alib_protos.h>
  27. #include <clib/exec_protos.h>
  28. #include <clib/dos_protos.h>
  29. #include <clib/asl_protos.h>
  30.  
  31. #include <pragmas/intuition_pragmas.h>
  32. #include <pragmas/utility_pragmas.h>
  33. #include <pragmas/locale_pragmas.h>
  34. #include <pragmas/exec_pragmas.h>
  35. #include <pragmas/dos_pragmas.h>
  36. #include <pragmas/asl_pragmas.h>
  37.  
  38. #include <string.h>
  39. #include <stdarg.h>
  40.  
  41.     /* Create the requester strings. */
  42.  
  43. #define CATCOMP_ARRAY
  44.  
  45. #include "AssignWedge.h"
  46.  
  47.     /* The requester selection IDs. */
  48.  
  49. enum    {    REQ_CANCEL, REQ_RETRY, REQ_ASSIGN, REQ_MOUNT, REQ_DENY };
  50.  
  51.     /* Some handy signal macros. */
  52.  
  53. #define SIG_KILL    SIGBREAKF_CTRL_C
  54. #define SIG_NOTIFY    (1L << MainPort -> mp_SigBit)
  55.  
  56.     /* The MC680x0 `jump to absolute address' opcode. */
  57.  
  58. #define JMP_ABS 0x4EF9
  59.  
  60.     /* A simple wedge definition which is to consist of a jmp
  61.      * instruction and the destination of the jump.
  62.      */
  63.  
  64. struct Wedge
  65. {
  66.     UWORD Command;
  67.     ULONG Location;
  68. };
  69.  
  70.     /* Process and command names which are no longer allowed to
  71.      * access certain paths will be identified by information
  72.      * to be found in a list. The following structure definition
  73.      * holds the necessary data (name and process base address).
  74.      */
  75.  
  76. struct DenyNode
  77. {
  78.     struct MinNode     Node;
  79.  
  80.     struct Process    *Process;
  81.     LONG             DenyEmpty;
  82.     STRPTR             Name,
  83.                      ProgramName;
  84. };
  85.  
  86.     /* The library vector offset of the intuition.library routine to patch. */
  87.  
  88. extern ULONG __far     LVOEasyRequestArgs;
  89.  
  90.     /* The version ID tag. */
  91.  
  92. STATIC UBYTE Version[]    = "\0$VER: AssignWedge 1.5 (18.1.95)\r\n";
  93.  
  94.     /* Global and shared library identifiers. */
  95.  
  96. struct IntuitionBase    *IntuitionBase;
  97. struct ExecBase            *SysBase;
  98. struct DosLibrary        *DOSBase;
  99. struct Library            *UtilityBase,
  100.                         *AslBase;
  101.  
  102.     /* Locale support. */
  103.  
  104. struct LocaleBase        *LocaleBase;
  105. struct Catalog            *Catalog;
  106.  
  107.     /* Registration of programs which are not allowed to
  108.      * access certain devices.
  109.      */
  110.  
  111. struct SignalSemaphore     DenySemaphore;
  112. struct MinList             DenyList;
  113.  
  114.     /* The following counter and the associated access semaphore help
  115.      * to keep track of the number of programs currently using the
  116.      * patched EasyRequestArgs() routine.
  117.      */
  118.  
  119. struct SignalSemaphore     RunSemaphore;
  120. LONG                     RunCount;
  121.  
  122.     /* Handshake data. */
  123.  
  124. struct Process            *MainProcess;
  125. struct MsgPort            *MainPort;
  126. BOOL                     Removed;
  127.  
  128.     /* To compensate for possible incompatibilities introduced by internationalized
  129.      * requester texts, we will try to determine the text to turn up when an
  130.      * `please insert volume' requester is opened. The `SearchName' will receive
  131.      * the string to look for.
  132.      */
  133.  
  134. UBYTE                     SearchName[256];
  135.  
  136.     /* Function prototypes. */
  137.  
  138. LONG __saveds             Main(VOID);
  139. STRPTR __regargs         GetString(LONG ID);
  140. LONG __saveds __asm         NewEasyRequestArgs(register __a0 struct Window *Window,register __a1 struct EasyStruct *EasyStruct,register __a2 ULONG *IDCMPPtr,register __a3 APTR *Args);
  141. LONG                    (* __asm OldEasyRequestArgs)(register __a0 struct Window *,register __a1 struct EasyStruct *,register __a2 ULONG *,register __a3 APTR *,register __a6 struct IntuitionBase *);
  142. LONG __stdargs             StackCall(LONG *Success,LONG StackSize,LONG ArgCount,LONG (* __stdargs Function)(),...);
  143. VOID __stdargs             SPrintf(STRPTR buffer,STRPTR formatString,...);
  144. VOID                     CheckIn(VOID);
  145. VOID                     CheckOut(VOID);
  146.  
  147. LONG __saveds
  148. Main()
  149. {
  150.     struct WBStartup    *WBenchMsg;
  151.     LONG                 ReturnCode = RETURN_FAIL;
  152.  
  153.         /* Set up ExecBase */
  154.  
  155.     SysBase = *(struct ExecBase **)4;
  156.  
  157.         /* Determine current process identifier. */
  158.  
  159.     MainProcess = (struct Process *)SysBase -> ThisTask;
  160.  
  161.         /* Are we running from CLI? If not, wait for Workbench
  162.          * startup message.
  163.          */
  164.  
  165.     if(!MainProcess -> pr_CLI)
  166.     {
  167.         WaitPort(&MainProcess -> pr_MsgPort);
  168.  
  169.         WBenchMsg = (struct WBStartup *)GetMsg(&MainProcess -> pr_MsgPort);
  170.     }
  171.     else
  172.         WBenchMsg = NULL;
  173.  
  174.         /* Try to find the global handshake port and if present
  175.          * send a termination signal.
  176.          */
  177.  
  178.     Forbid();
  179.  
  180.     if(MainPort = FindPort("AssignWedge Rendezvous"))
  181.     {
  182.         Signal(MainPort -> mp_SigTask,SIG_KILL);
  183.  
  184.         ReturnCode = RETURN_OK;
  185.  
  186.         Permit();
  187.     }
  188.     else
  189.     {
  190.         Permit();
  191.  
  192.             /* Are we running under Kickstart version 37 or higher? */
  193.  
  194.         if(SysBase -> LibNode . lib_Version > 36)
  195.         {
  196.                 /* Create the global handshake port. */
  197.  
  198.             if(MainPort = CreateMsgPort())
  199.             {
  200.                     /* Give it a name and add it to the public list. */
  201.  
  202.                 MainPort -> mp_Node . ln_Name = "AssignWedge Rendezvous";
  203.  
  204.                 AddPort(MainPort);
  205.  
  206.                     /* Open the required libraries. */
  207.  
  208.                 if(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",37))
  209.                 {
  210.                     if(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37))
  211.                     {
  212.                         if(UtilityBase = OpenLibrary("utility.library",37))
  213.                         {
  214.                             if(AslBase = OpenLibrary(AslName,37))
  215.                             {
  216.                                 struct Wedge *Wedge;
  217.  
  218.                                     /* Try to open locale.library, but don't panic
  219.                                      * if it's not available.
  220.                                      */
  221.  
  222.                                 if(LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library",38))
  223.                                 {
  224.                                     if(!(Catalog = OpenCatalog(NULL,"assignwedge.catalog",
  225.                                         OC_BuiltInLanguage,    "english",
  226.                                         OC_BuiltInCodeSet,    0,
  227.                                     TAG_DONE)))
  228.                                     {
  229.                                         CloseLibrary((struct Library *)LocaleBase);
  230.  
  231.                                         LocaleBase = NULL;
  232.                                     }
  233.                                 }
  234.  
  235.                                     /* Initialize the access semaphore. */
  236.  
  237.                                 InitSemaphore(&RunSemaphore);
  238.  
  239.                                 RunCount = 0;
  240.  
  241.                                     /* Initialize the access semaphore and
  242.                                      * the list of programs to which access
  243.                                      * to certain devices has been denied.
  244.                                      */
  245.  
  246.                                 InitSemaphore(&DenySemaphore);
  247.  
  248.                                 NewList((struct List *)&DenyList);
  249.  
  250.                                     /* Allocate a system library function wedge. */
  251.  
  252.                                 if(Wedge = AllocMem(sizeof(struct Wedge),MEMF_PUBLIC))
  253.                                 {
  254.                                     struct DenyNode    *NextNode,
  255.                                                     *DenyNode;
  256.                                     UBYTE             LocalBuffer[80];
  257.  
  258.                                         /* Initialize the wedge. */
  259.  
  260.                                     Wedge -> Command    = JMP_ABS;
  261.                                     Wedge -> Location    = (ULONG)NewEasyRequestArgs;
  262.  
  263.                                     Removed = FALSE;
  264.  
  265.                                         /* Install the wedge. */
  266.  
  267.                                     Forbid();
  268.  
  269.                                     OldEasyRequestArgs = (LONG (* __asm)())SetFunction((struct Library *)IntuitionBase,(LONG)&LVOEasyRequestArgs,(ULONG (*)())Wedge);
  270.  
  271.                                         /* Make sure the data gets written to memory. */
  272.  
  273.                                     CacheClearU();
  274.  
  275.                                         /* Put up an example requester. Note: this requester
  276.                                          * will be trapped by the wedge routine, giving us
  277.                                          * the string to look for in the future.
  278.                                          */
  279.  
  280.                                     SPrintf(LocalBuffer,"AssignWedge.%08lx:",MainProcess);
  281.  
  282.                                     ErrorReport(ERROR_DEVICE_NOT_MOUNTED,REPORT_INSERT,(ULONG)LocalBuffer,NULL);
  283.  
  284.                                         /* We're up and running now. Note that the
  285.                                          * Forbid() will be broken by the Wait() for
  286.                                          * a ^C signal.
  287.                                          */
  288.  
  289.                                     Wait(SIG_KILL);
  290.  
  291.                                         /* We are no longer running,
  292.                                          * tell the wedge routine to
  293.                                          * skip the `access denied'
  294.                                          * part which requires the
  295.                                          * list to be initialized.
  296.                                          */
  297.  
  298.                                     Removed = TRUE;
  299.  
  300.                                         /* Redirect the wedge pointer to
  301.                                          * the original routine.
  302.                                          */
  303.  
  304.                                     Wedge -> Location = (ULONG)OldEasyRequestArgs;
  305.  
  306.                                         /* Make sure that the data
  307.                                          * gets written to memory.
  308.                                          */
  309.  
  310.                                     CacheClearU();
  311.  
  312.                                         /* Clear pending signals. */
  313.  
  314.                                     SetSignal(0,SIG_NOTIFY);
  315.  
  316.                                         /* Turn the multitasking back on. */
  317.  
  318.                                     Permit();
  319.  
  320.                                         /* Wait until our wedge routine
  321.                                          * is no longer in use.
  322.                                          */
  323.  
  324.                                     while(RunCount)
  325.                                         Wait(SIG_NOTIFY);
  326.  
  327.                                         /* Clear the `access denied' list. */
  328.  
  329.                                     DenyNode = (struct DenyNode *)DenyList . mlh_Head;
  330.  
  331.                                     while(NextNode = (struct DenyNode *)DenyNode -> Node . mln_Succ)
  332.                                     {
  333.                                         FreeVec(DenyNode);
  334.  
  335.                                         DenyNode = NextNode;
  336.                                     }
  337.  
  338.                                         /* Successful termination. */
  339.  
  340.                                     ReturnCode = RETURN_OK;
  341.                                 }
  342.  
  343.                                     /* Close the resources
  344.                                      * we had allocated,
  345.                                      * but *not* the wedge
  346.                                      * memory.
  347.                                      */
  348.  
  349.                                 if(Catalog)
  350.                                     CloseCatalog(Catalog);
  351.  
  352.                                 if(LocaleBase)
  353.                                     CloseLibrary((struct Library *)LocaleBase);
  354.  
  355.                                 CloseLibrary(AslBase);
  356.                             }
  357.  
  358.                             CloseLibrary(UtilityBase);
  359.                         }
  360.  
  361.                         CloseLibrary((struct Library *)IntuitionBase);
  362.                     }
  363.  
  364.                     CloseLibrary((struct Library *)DOSBase);
  365.                 }
  366.  
  367.                     /* Remove the global handshake port. */
  368.  
  369.                 RemPort(MainPort);
  370.  
  371.                 DeleteMsgPort(MainPort);
  372.             }
  373.         }
  374.     }
  375.  
  376.         /* If run from Workbench, reply the startup message. */
  377.  
  378.     if(WBenchMsg)
  379.     {
  380.         Forbid();
  381.  
  382.         ReplyMsg(&WBenchMsg -> sm_Message);
  383.     }
  384.  
  385.         /* That's all folks. */
  386.  
  387.     return(ReturnCode);
  388. }
  389.  
  390.     /* GetString(LONG ID):
  391.      *
  392.      *    Fetch a text from the database.
  393.      */
  394.  
  395. STRPTR __regargs
  396. GetString(LONG ID)
  397. {
  398.     STRPTR    Builtin = "";
  399.     WORD    i;
  400.  
  401.         /* Try to find the builtin string to match the ID we received. */
  402.  
  403.     if(CatCompArray[ID] . cca_ID != ID)
  404.     {
  405.         for(i = 0 ; i < (sizeof(CatCompArray) / sizeof(struct CatCompArrayType)) ; i++)
  406.         {
  407.             if(CatCompArray[i] . cca_ID == ID)
  408.             {
  409.                 Builtin = CatCompArray[i] . cca_Str;
  410.  
  411.                 break;
  412.             }
  413.         }
  414.     }
  415.     else
  416.         Builtin = CatCompArray[ID] . cca_Str;
  417.  
  418.         /* If locale.library is installed and the database catalog was
  419.          * successfully opened, query the library's idea of the corresponding
  420.          * text string. Otherwise, return the builtin string.
  421.          */
  422.  
  423.     if(LocaleBase)
  424.         return(GetCatalogStr(Catalog,ID,Builtin));
  425.     else
  426.         return(Builtin);
  427. }
  428.  
  429.     /* SPrintf(STRPTR buffer,STRPTR formatString,...):
  430.      *
  431.      *    Your easy text formatting routine.
  432.      */
  433.  
  434. VOID __stdargs
  435. SPrintf(STRPTR buffer,STRPTR formatString,...)
  436. {
  437.     va_list varArgs;
  438.  
  439.     va_start(varArgs,formatString);
  440.     RawDoFmt(formatString,varArgs,(VOID (*)())(VOID (*))"\x16\xC0\x4E\x75",buffer);
  441.     va_end(varArgs);
  442. }
  443.  
  444.     /* CheckIn():
  445.      *
  446.      *    Mark the patch as having another customer.
  447.      */
  448.  
  449. VOID
  450. CheckIn()
  451. {
  452.         /* Increment the usage count. */
  453.  
  454.     ObtainSemaphore(&RunSemaphore);
  455.  
  456.     RunCount++;
  457.  
  458.     ReleaseSemaphore(&RunSemaphore);
  459. }
  460.  
  461.     /* CheckOut():
  462.      *
  463.      *    Decrement the patch usage counter and signal the
  464.      *    main process to check the usage counter.
  465.      */
  466.  
  467. VOID
  468. CheckOut()
  469. {
  470.         /* Decrement usage count. */
  471.  
  472.     ObtainSemaphore(&RunSemaphore);
  473.  
  474.     RunCount--;
  475.  
  476.     ReleaseSemaphore(&RunSemaphore);
  477.  
  478.         /* Tell the main process to take a
  479.          * look at the usage count.
  480.          */
  481.  
  482.     Signal((struct Task *)MainProcess,SIG_NOTIFY);
  483. }
  484.  
  485.     /* RealEasyRequestArgs():
  486.      *
  487.      *    Custom version of EasyRequestArgs().
  488.      */
  489.  
  490. LONG __stdargs
  491. RealEasyRequestArgs(struct Window *Window,struct EasyStruct *EasyStruct,ULONG *IDCMPPtr,APTR *Args)
  492. {
  493.     struct Process    *ThisProcess = (struct Process *)SysBase -> ThisTask;
  494.     LONG             Result;
  495.  
  496.         /* Increment the usage count. */
  497.  
  498.     CheckIn();
  499.  
  500.         /* Is the caller a process, i.e. will it be able to use all
  501.          * DOS routines?
  502.          */
  503.  
  504.     if(ThisProcess -> pr_Task . tc_Node . ln_Type == NT_PROCESS)
  505.     {
  506.             /* Do the arguments match the pattern we had expected and
  507.              * are DOS requesters enabled?
  508.              */
  509.  
  510.         if(!Strnicmp(EasyStruct -> es_TextFormat,"%s",2) && Args && ThisProcess -> pr_WindowPtr != (APTR)-1)
  511.         {
  512.                 /* Did we get any calling parameters? */
  513.  
  514.             if(Args[0])
  515.             {
  516.                     /* Does the first argument match the `please insert volume...' title? */
  517.  
  518.                 if(!Stricmp(Args[0],SearchName))
  519.                 {
  520.                     struct EasyStruct __aligned     Easy = *EasyStruct;
  521.                     UBYTE                         DirBuffer[512 + 60];
  522.                     STRPTR                         HailBuffer;
  523.                     struct DenyNode                *DenyNode;
  524.                     struct FileRequester        *AslFileRequest;
  525.                     struct Screen                *FirstScreen;
  526.                     ULONG                         IntuiLock;
  527.                     BPTR                         In,Out;
  528.  
  529.                         /* Gain access to the list of
  530.                          * programs to which access to
  531.                          * some devices has been denied.
  532.                          */
  533.  
  534.                     ObtainSemaphore(&DenySemaphore);
  535.  
  536.                         /* If this process has a CLI structure
  537.                          * attached, look for a command name
  538.                          * to match a list entry.
  539.                          */
  540.  
  541.                     if(ThisProcess -> pr_CLI)
  542.                     {
  543.                             /* Process the list... */
  544.  
  545.                         for(DenyNode = (struct DenyNode *)DenyList . mlh_Head ; DenyNode -> Node . mln_Succ ; DenyNode = (struct DenyNode *)DenyNode -> Node . mln_Succ)
  546.                         {
  547.                                 /* Does this entry refer to
  548.                                  * a command name?
  549.                                  */
  550.  
  551.                             if(DenyNode -> ProgramName[0])
  552.                             {
  553.                                     /* Does the name of the device
  554.                                      * in question match the name
  555.                                      * in the list entry?
  556.                                      */
  557.  
  558.                                 if(!Stricmp(DenyNode -> Name,Args[1]))
  559.                                 {
  560.                                         /* Obtain the name of the program
  561.                                          * currently running.
  562.                                          */
  563.  
  564.                                     if(GetProgramName(DirBuffer,512))
  565.                                     {
  566.                                             /* Does the name match the one
  567.                                              * in the list entry?
  568.                                              */
  569.  
  570.                                         if(!Stricmp(FilePart(DirBuffer),DenyNode -> ProgramName))
  571.                                         {
  572.                                                 /* Release the access semaphore. */
  573.  
  574.                                             ReleaseSemaphore(&DenySemaphore);
  575.  
  576.                                                 /* Decrement usage count. */
  577.  
  578.                                             CheckOut();
  579.  
  580.                                                 /* Return failure. */
  581.  
  582.                                             return(REQ_CANCEL);
  583.                                         }
  584.                                     }
  585.                                 }
  586.                             }
  587.                             else
  588.                             {
  589.                                     /* This might be an `empty' Shell. Let's have a look. */
  590.  
  591.                                 if(!GetProgramName(DirBuffer,512))
  592.                                     DirBuffer[0] = 0;
  593.  
  594.                                     /* No command loaded? */
  595.  
  596.                                 if(!DirBuffer[0])
  597.                                 {
  598.                                         /* Release the access semaphore. */
  599.  
  600.                                     ReleaseSemaphore(&DenySemaphore);
  601.  
  602.                                         /* Decrement usage count. */
  603.  
  604.                                     CheckOut();
  605.  
  606.                                         /* Return failure. */
  607.  
  608.                                     return(REQ_CANCEL);
  609.                                 }
  610.                             }
  611.                         }
  612.                     }
  613.                     else
  614.                     {
  615.                             /* Run down the list. */
  616.  
  617.                         for(DenyNode = (struct DenyNode *)DenyList . mlh_Head ; DenyNode -> Node . mln_Succ ; DenyNode = (struct DenyNode *)DenyNode -> Node . mln_Succ)
  618.                         {
  619.                                 /* Does the process identifier match the
  620.                                  * one in the list entry?
  621.                                  */
  622.  
  623.                             if(DenyNode -> Process == ThisProcess)
  624.                             {
  625.                                     /* Does the name of the device in
  626.                                      * question match the one in the
  627.                                      * list entry?
  628.                                      */
  629.  
  630.                                 if(!Stricmp(DenyNode -> Name,Args[1]))
  631.                                 {
  632.                                         /* Release the access semaphore. */
  633.  
  634.                                     ReleaseSemaphore(&DenySemaphore);
  635.  
  636.                                         /* Decrement usage count. */
  637.  
  638.                                     CheckOut();
  639.  
  640.                                         /* Return failure. */
  641.  
  642.                                     return(REQ_CANCEL);
  643.                                 }
  644.                             }
  645.                         }
  646.                     }
  647.  
  648.                         /* Release the access semaphore. */
  649.  
  650.                     ReleaseSemaphore(&DenySemaphore);
  651.  
  652.                         /* Split the buffer to create the directory
  653.                          * requester title string.
  654.                          */
  655.  
  656.                     HailBuffer = DirBuffer + 512;
  657.  
  658.                         /* Fill in the `Retry|Assign|Mount|Deny|Cancel' buttons. */
  659.  
  660.                     Easy . es_GadgetFormat = GetString(MSG_PROMPT_GAD);
  661.  
  662.                         /* Put up the requester and decide what to do. */
  663.  
  664.                     switch(Result = OldEasyRequestArgs(Window,&Easy,IDCMPPtr,Args,IntuitionBase))
  665.                     {
  666.                         case REQ_ASSIGN:
  667.  
  668.                                 /* Try to obtain the name of the current directory,
  669.                                  * most programs to look for assignments or volume
  670.                                  * names will be happy if assignments are made
  671.                                  * referring to their home directories.
  672.                                  */
  673.  
  674.                             if(ThisProcess -> pr_HomeDir)
  675.                             {
  676.                                 if(!NameFromLock(ThisProcess -> pr_HomeDir,DirBuffer,512))
  677.                                     DirBuffer[0] = 0;
  678.                             }
  679.                             else
  680.                                 DirBuffer[0] = 0;
  681.  
  682.                                 /* No success? */
  683.  
  684.                             if(!DirBuffer[0])
  685.                             {
  686.                                 if(!GetCurrentDirName(DirBuffer,512))
  687.                                     DirBuffer[0] = 0;
  688.                             }
  689.  
  690.                                 /* Set up the window title. */
  691.  
  692.                             SPrintf(HailBuffer,GetString(MSG_HAIL_GAD),Args[1]);
  693.  
  694.                                 /* create the directory requester. */
  695.  
  696.                             if(AslFileRequest = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
  697.                                 ASLFR_InitialDrawer,    DirBuffer,
  698.                                 ASLFR_TitleText,        HailBuffer,
  699.                                 ASLFR_PositiveText,        GetString(MSG_ASSIGN_GAD),
  700.                                 ASLFR_DrawersOnly,        TRUE,
  701.                                 ASLFR_PrivateIDCMP,        TRUE,
  702.  
  703.                                     /* These are actually for asl.library v36/v37. */
  704.  
  705.                                 ASL_FuncFlags,            FILF_NEWIDCMP,
  706.                                 ASL_ExtFlags1,            FIL1F_NOFILES,
  707.  
  708.                                 Window ? ASLFR_Window : TAG_IGNORE,        Window,
  709.                             TAG_DONE))
  710.                             {
  711.                                     /* Remember the first screen ID. */
  712.  
  713.                                 IntuiLock = LockIBase(NULL);
  714.  
  715.                                 FirstScreen = IntuitionBase -> FirstScreen;
  716.  
  717.                                 UnlockIBase(IntuiLock);
  718.  
  719.                                     /* Did we receive a window pointer to work with? */
  720.  
  721.                                 if(Window)
  722.                                 {
  723.                                         /* Move the screen the requester is to appear on
  724.                                          * up if necessary.
  725.                                          */
  726.  
  727.                                     if(Window -> WScreen -> TopEdge > 0)
  728.                                         MoveScreen(Window -> WScreen,0,-Window -> WScreen -> TopEdge);
  729.  
  730.                                         /* Move the screen to the front. */
  731.  
  732.                                     ScreenToFront(Window -> WScreen);
  733.                                 }
  734.                                 else
  735.                                 {
  736.                                         /* Get the current default public screen. */
  737.  
  738.                                     struct Screen *Workbench = LockPubScreen(NULL);
  739.  
  740.                                         /* Did we succeed in locking it? */
  741.  
  742.                                     if(Workbench)
  743.                                     {
  744.                                             /* Move the screen the requester is to appear on
  745.                                              * up if necessary.
  746.                                              */
  747.  
  748.                                         if(Workbench -> TopEdge > 0)
  749.                                             MoveScreen(Workbench,0,-Workbench -> TopEdge);
  750.  
  751.                                             /* Move the screen to the front. */
  752.  
  753.                                         ScreenToFront(Workbench);
  754.  
  755.                                             /* Release the screen again. */
  756.  
  757.                                         UnlockPubScreen(NULL,Workbench);
  758.                                     }
  759.                                 }
  760.  
  761.                                     /* Display the requester. */
  762.  
  763.                                 while(AslRequest(AslFileRequest,NULL))
  764.                                 {
  765.                                     APTR OldWindowPtr = ThisProcess -> pr_WindowPtr;
  766.                                     BPTR FileLock;
  767.  
  768.                                         /* Disable the system requesters. */
  769.  
  770.                                     ThisProcess -> pr_WindowPtr = (APTR)-1;
  771.  
  772.                                         /* Try to access the directory the
  773.                                          * user has just selected.
  774.                                          */
  775.  
  776.                                     if(FileLock = Lock(AslFileRequest -> fr_Drawer,ACCESS_READ))
  777.                                     {
  778.                                             /* Try to create the assignment. */
  779.  
  780.                                         if(!AssignLock(Args[1],FileLock))
  781.                                         {
  782.                                                 /* Oops, something went wrong. */
  783.  
  784.                                             if(Window)
  785.                                                 DisplayBeep(Window -> WScreen);
  786.                                             else
  787.                                                 DisplayBeep(NULL);
  788.  
  789.                                             UnLock(FileLock);
  790.                                         }
  791.                                         else
  792.                                         {
  793.                                                 /* Restore the window pointer. */
  794.  
  795.                                             ThisProcess -> pr_WindowPtr = OldWindowPtr;
  796.  
  797.                                             break;
  798.                                         }
  799.                                     }
  800.                                     else
  801.                                     {
  802.                                         if(Window)
  803.                                             DisplayBeep(Window -> WScreen);
  804.                                         else
  805.                                             DisplayBeep(NULL);
  806.                                     }
  807.  
  808.                                         /* Restore the window pointer. */
  809.  
  810.                                     ThisProcess -> pr_WindowPtr = OldWindowPtr;
  811.                                 }
  812.  
  813.                                     /* Free the requester data. */
  814.  
  815.                                 FreeAslRequest(AslFileRequest);
  816.  
  817.                                     /* Pop the screen which was frontmost
  818.                                      * before the requester was displayed
  819.                                      * back to the front.
  820.                                      */
  821.  
  822.                                 IntuiLock = LockIBase(0);
  823.  
  824.                                 if(FirstScreen == IntuitionBase -> FirstScreen)
  825.                                     UnlockIBase(IntuiLock);
  826.                                 else
  827.                                 {
  828.                                     struct Screen    *Screen = IntuitionBase -> FirstScreen;
  829.                                     BOOL             IsValid = FALSE;
  830.  
  831.                                         /* Try to determine if the screen ID we
  832.                                          * remembered is still valid.
  833.                                          */
  834.  
  835.                                     while(Screen && !IsValid)
  836.                                     {
  837.                                         if(Screen == FirstScreen)
  838.                                             IsValid = TRUE;
  839.                                         else
  840.                                             Screen = Screen -> NextScreen;
  841.                                     }
  842.  
  843.                                     Forbid();
  844.  
  845.                                     UnlockIBase(IntuiLock);
  846.  
  847.                                         /* Push the screen to the front. */
  848.  
  849.                                     if(IsValid)
  850.                                         ScreenToFront(FirstScreen);
  851.  
  852.                                     Permit();
  853.                                 }
  854.                             }
  855.  
  856.                                 /* Tell AmigaDOS to take a second look at the
  857.                                  * device list.
  858.                                  */
  859.  
  860.                             Result = REQ_RETRY;
  861.  
  862.                             break;
  863.  
  864.                         case REQ_MOUNT:
  865.  
  866.                                 /* Open input stream. */
  867.  
  868.                             if(In = Open("NIL:",MODE_OLDFILE))
  869.                             {
  870.                                     /* Open output stream. */
  871.  
  872.                                 if(Out = Open("NIL:",MODE_OLDFILE))
  873.                                 {
  874.                                     APTR OldPtr = ThisProcess -> pr_WindowPtr;
  875.  
  876.                                         /* Enter the mount command string. */
  877.  
  878.                                     SPrintf(DirBuffer,"Mount >NIL: <NIL: %s:",Args[1]);
  879.  
  880.                                         /* Disable DOS requesters. */
  881.  
  882.                                     ThisProcess -> pr_WindowPtr = (APTR)-1;
  883.  
  884.                                         /* Execute the mount command. */
  885.  
  886.                                     SystemTags(DirBuffer,
  887.                                         NP_Cli,            TRUE,
  888.                                         NP_CloseInput,    TRUE,
  889.                                         NP_CloseOutput,    TRUE,
  890.  
  891.                                         SYS_UserShell,    TRUE,
  892.                                         SYS_Input,        In,
  893.                                         SYS_Output,        Out,
  894.                                     TAG_DONE);
  895.  
  896.                                         /* Restore window pointer. */
  897.  
  898.                                     if(ThisProcess -> pr_WindowPtr == (APTR)-1)
  899.                                         ThisProcess -> pr_WindowPtr = OldPtr;
  900.                                 }
  901.                                 else
  902.                                     Close(In);
  903.                             }
  904.  
  905.                                 /* Tell AmigaDOS to take a second look at the
  906.                                  * device list.
  907.                                  */
  908.  
  909.                             Result = REQ_RETRY;
  910.  
  911.                             break;
  912.  
  913.                         case REQ_DENY:
  914.  
  915.                                 /* If not about to be removed, allocate an `access denied' node. */
  916.  
  917.                             if(!Removed)
  918.                             {
  919.                                 WORD    ProgramNameLen = 0,
  920.                                         DeviceNameLen;
  921.                                 LONG    DenyEmpty = FALSE;
  922.  
  923.                                     /* Remember the length of the device name. */
  924.  
  925.                                 DeviceNameLen = strlen(Args[1]) + 1;
  926.  
  927.                                     /* If this process has a CLI structure attached,
  928.                                      * remember the name of the program.
  929.                                      */
  930.  
  931.                                 if(ThisProcess -> pr_CLI)
  932.                                 {
  933.                                         /* Is there a command making the request? */
  934.  
  935.                                     if(!GetProgramName(DirBuffer,512))
  936.                                         DirBuffer[0] = 0;
  937.  
  938.                                         /* Keep the name. */
  939.  
  940.                                     if(DirBuffer[0])
  941.                                         ProgramNameLen = strlen(FilePart(DirBuffer)) + 1;
  942.                                     else
  943.                                         DenyEmpty = TRUE;
  944.                                 }
  945.  
  946.                                     /* Allocate a new deny node. */
  947.  
  948.                                 if(DenyNode = (struct DenyNode *)AllocVec(sizeof(struct DenyNode) + DeviceNameLen + ProgramNameLen,MEMF_CLEAR))
  949.                                 {
  950.                                         /* Deny `empty' Shells? */
  951.  
  952.                                     DenyNode -> DenyEmpty = DenyEmpty;
  953.  
  954.                                         /* Fill in the current process ID. */
  955.  
  956.                                     DenyNode -> Process = ThisProcess;
  957.  
  958.                                         /* Copy the name of the device in question. */
  959.  
  960.                                     strcpy(DenyNode -> Name = (STRPTR)(DenyNode + 1),Args[1]);
  961.  
  962.                                         /* Copy the program name if possible. */
  963.  
  964.                                     if(ProgramNameLen)
  965.                                         strcpy(DenyNode -> ProgramName = DenyNode -> Name + DeviceNameLen,FilePart(DirBuffer));
  966.                                     else
  967.                                         DenyNode -> ProgramName = "";
  968.  
  969.                                         /* Gain access to the list. */
  970.  
  971.                                     ObtainSemaphore(&DenySemaphore);
  972.  
  973.                                         /* Add the entry to the list. */
  974.  
  975.                                     AddTail((struct List *)&DenyList,(struct Node *)DenyNode);
  976.  
  977.                                         /* Release the semaphore again. */
  978.  
  979.                                     ReleaseSemaphore(&DenySemaphore);
  980.                                 }
  981.                             }
  982.  
  983.                                 /* Return failure. */
  984.  
  985.                             Result = REQ_CANCEL;
  986.                             break;
  987.                     }
  988.  
  989.                         /* Decrement usage count. */
  990.  
  991.                     CheckOut();
  992.  
  993.                         /* Return the result. */
  994.  
  995.                     return(Result);
  996.                 }
  997.             }
  998.         }
  999.     }
  1000.  
  1001.         /* In any other case, use the standard call. */
  1002.  
  1003.     Result = OldEasyRequestArgs(Window,EasyStruct,IDCMPPtr,Args,IntuitionBase);
  1004.  
  1005.         /* Decrement usage count. */
  1006.  
  1007.     CheckOut();
  1008.  
  1009.         /* Return the result. */
  1010.  
  1011.     return(Result);
  1012. }
  1013.  
  1014.     /* NewEasyRequestArgs():
  1015.      *
  1016.      *    A custom version of the original EasyRequest() routine which
  1017.      *    is to provide enhanced options whenever a DOS handler puts
  1018.      *    up a `REPORT_INSERT' style requester.
  1019.      */
  1020.  
  1021. LONG __saveds __asm
  1022. NewEasyRequestArgs(register __a0 struct Window *Window,register __a1 struct EasyStruct *EasyStruct,register __a2 ULONG *IDCMPPtr,register __a3 APTR *Args)
  1023. {
  1024.     struct Process *ThisProcess = (struct Process *)SysBase -> ThisTask;
  1025.  
  1026.         /* This may be the first call to the new routine, made by the
  1027.          * main program trying to determine the text to look for in
  1028.          * future requesters.
  1029.          */
  1030.  
  1031.     if(!SearchName[0] && ThisProcess == MainProcess)
  1032.     {
  1033.         strcpy(SearchName,Args[0]);
  1034.  
  1035.         return(REQ_CANCEL);
  1036.     }
  1037.     else
  1038.     {
  1039.         LONG Success,Result;
  1040.  
  1041.             /* Allocate extra stack space, call the special routine. */
  1042.  
  1043.         Result = StackCall(&Success,8192,4,RealEasyRequestArgs,Window,EasyStruct,IDCMPPtr,Args);
  1044.  
  1045.             /* If the call did not succeed, do it the standard way. */
  1046.  
  1047.         if(!Success)
  1048.         {
  1049.                 /* Increment the usage count. */
  1050.  
  1051.             CheckIn();
  1052.  
  1053.                 /* Call the original routine. */
  1054.  
  1055.             Result = OldEasyRequestArgs(Window,EasyStruct,IDCMPPtr,Args,IntuitionBase);
  1056.  
  1057.                 /* Decrement usage count. */
  1058.  
  1059.             CheckOut();
  1060.         }
  1061.  
  1062.             /* Return the result. */
  1063.  
  1064.         return(Result);
  1065.     }
  1066. }
  1067.